import csv

from originAppfreeze import Originfreeze
from readFile import ReadFile


class cppProcess(Originfreeze):

    def __init__(self, perFileData):
        super().__init__(perFileData)
        self.contents = perFileData
        self.dfx = ['[anon:libc_malloc]', 'Unknown', '[anon:.bss]', '[heap]', '[stack]']
        self.clibs = ['libc.so', 'libc++', 'glibc', 'musl', 'bionic', 'libutils', 'ipc', "Not mapped"]
        self.all_so_row_list = self.getSoAndRowList()
        self.not_clibs_so = self.getNotClibsSo()
        self.not_clibs_list = self.getNotClibsSolist()
        self.stack = self.getValidSo()[0]
        self.basis_so = self.getValidSo()[1]
        self.foundstatus = self.getStatus()
        '''
            foundstatus 1: 'Exception'
            foundstatus 2: 'valid So'
            foundstatus 3: 'Invalid So'
            foundstatus 4: 'Testcase'
            foundstatus 5: 'DFX related'
        '''
        self.is_crucial_app = self.isCrucialApp()

    def getSoAndRowList(self):
        solist = []
        ori_solist = self.ori_solist
        if ori_solist is None:
            return None
        for line in ori_solist:
            curline: str = line
            cur_so_row = curline.split("pc ")[-1]
            solist.append(cur_so_row)
        return solist

    def getNotClibsSo(self):
        if self.all_so_row_list is None:
            return None
        for per_so_row in self.all_so_row_list:
            cur_so = per_so_row.split('(')[0].split("/")[-1]
            if self.notClib(cur_so) and (not self.isDfxSo(cur_so)) and (cur_so != ''):
                return cur_so
        return None

    def getNotClibsSolist(self):
        if self.all_so_row_list is None:
            return None
        not_clib_all_so_row_list = []
        for per_so_row in self.all_so_row_list:
            not_clib_all_so_row_list.append(per_so_row)
            cur_so = per_so_row.split('(')[0].split('/')[-1]
            if self.notClib(cur_so) and (not self.isDfxSo(cur_so)) and (cur_so != ''):
                return not_clib_all_so_row_list
        return self.all_so_row_list

    @staticmethod
    def ifStrInList(target, ls):
        # target = target.lower()
        for s in ls:
            if target in s:
                return s
        return ''

    @staticmethod
    def cutName(prin_name: str):
        if ' ' in prin_name.strip():
            return prin_name.split()[0]
        else:
            ret = ''
            for s in prin_name:
                if s.isnumeric():
                    return ret
                ret += s
            return ret

    def notClib(self, per_so: str):
        for clib in self.clibs:
            if clib in per_so:
                idx = per_so.index(clib) + len(clib)
                if len(per_so) > idx:
                    if not (97 <= ord(per_so[idx].lower()) <= 122):
                        return False
                else:
                    return False
        return True

    def libaceNapi(self, cur_so, cur_all_so_row_list):
        if self.all_so_row_list == None or cur_so == None:
            return None
        if "ark" in cur_so:
            napi_status = 0
            # 没找到这一行, status=0
            for so_idx in range(len(self.ori_solist)):
                # 原始的完整 so
                per_ori_line = self.ori_solist[so_idx]
                if napi_status == 0:
                    if per_ori_line.count('/') >= 1:
                        if per_ori_line.split('/')[-1].startswith('libace_napi'):
                            napi_status = 1
                    else:
                        pass
                if napi_status == 1:
                    if (per_ori_line.split()[-1].startswith('/system/lib/module/') or
                            per_ori_line.split()[-1].startswith('/system/lib64/module/')) and \
                            (not per_ori_line.split('/')[-1].startswith('libace')):
                        so_row = per_ori_line.split('/')[-1]
                        stack = so_row.split('(')[0]
                        return stack, self.all_so_row_list[: so_idx + 1]
                    else:
                        pass
        return None

    def multiThread(self):
        multhread = 0
        multilist = []
        if self.all_so_row_list is None:
            return None
        for per_so_row in self.all_so_row_list:
            multilist.append(per_so_row)
            if multhread == 0:
                if 'abort' in per_so_row:
                    multhread = 1
            elif multhread == 1:
                if self.notClib(per_so_row) and 'ark' not in per_so_row:
                    cur_so = per_so_row.split('(')[0].split('/')[-1]
                    return cur_so, multilist
                if self.notClib(per_so_row) and 'ark' in per_so_row:
                    multhread = 2
            elif multhread == 2:
                if self.notClib(per_so_row) and 'ark' not in per_so_row:
                    cur_so = per_so_row.split('(')[0].split('/')[-1]
                    return cur_so, multilist
        return None

    def getValidSo(self):
        if self.all_so_row_list == None:
            return None, None
        multi = self.multiThread()
        if multi:
            cur_so, cur_all_so_row_list = multi
            napi = self.libaceNapi(cur_so, cur_all_so_row_list)
            if napi:
                return napi
            else:
                return multi
        else:
            cur_so = self.not_clibs_so
            cur_all_so_row_list = self.all_so_row_list
            napi = self.libaceNapi(cur_so, cur_all_so_row_list)
            if napi:
                return napi
            else:
                return self.not_clibs_so, self.not_clibs_list

    def isCrucialApp(self):
        crucial = ["com.ohos.mms", "com.ohos.photos", "com.ohos.note", "com.example.kikakeyboard",
                   "com.ohos.callui", "com.ohos.camera", "com.ohos.contacts", "com.ohos.settings",
                   "com.ohos.systemui", "com.ohos.screenlock", "com.ohos.launcher"]
        for c_app in crucial:
            if c_app in self.package_name:
                return c_app
        return False

    def isTestCase(self):
        testcase = ['test', 'acts', 'ceshi']
        for word in testcase:
            if word in self.package_name:
                return True
        return False

    def isDfxSo(self, per_so):
        if per_so is None:
            return False
        for per_s in self.dfx:
            if per_s in per_so:
                return True
        return False

    def isDfx(self):
        if self.all_so_row_list is None:
            return False
        for so_row in self.all_so_row_list:
            for per_s in self.dfx:
                if per_s in so_row:
                    return True
        return False

    def getStatus(self):
        '''
            foundstatus 1: 'Exception'
            foundstatus 2: 'valid So'
            foundstatus 3: 'Invalid So'
            foundstatus 4: 'Testcase'
            foundstatus 5: 'DFX related'
        '''
        if self.all_so_row_list is None:
            return 1
        if self.stack is None:
            if self.isTestCase():
                return 4
            elif self.isDfx():
                return 5
            else:
                return 3
        else:
            if self.isTestCase():
                return 4
            else:
                return 2

    def getOriginValidSoList(self):
        if self.all_so_row_list is None:
            return []
        orivalidsolist = []
        for per_so_row in self.all_so_row_list:
            orivalidsolist.append(per_so_row)
            if per_so_row.count('(') >= 1:
                per_so = per_so_row.split('(')[0].split('/')[-1]
            else:
                per_so = per_so_row
            if self.notClib(per_so):
                return orivalidsolist
            else:
                pass
        return orivalidsolist
